home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / FWStream / Sources / SLBufSin.cpp < prev    next >
Encoding:
Text File  |  1996-08-16  |  22.1 KB  |  666 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLBufSin.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFound.hpp"
  11.  
  12. #include <Limits.h>
  13.  
  14. #ifndef FWEXCDEF_H
  15. #include "FWExcDef.h"
  16. #endif
  17.  
  18. #ifndef FWPRIDEB_H
  19. #include "FWPriDeb.h"
  20. #endif
  21.  
  22. #ifndef SLSTRMRW_H
  23. #include "SLStrmRW.h"
  24. #endif
  25.  
  26. #ifdef FW_BUILD_MAC
  27. #pragma segment FWStream
  28. #endif
  29.  
  30.  
  31. /*
  32.  *  This file was generated by the SOM Compiler.
  33.  *  Generated using: 
  34.  *      SOM Emitter emitxtm.dll: 2.33
  35.  */
  36.  
  37. #define VARIABLE_MACROS
  38. #define FW_OBufferedSink_Class_Source
  39. #include "SLBufSin.xih"
  40.  
  41. // [KVV] Work around a Visual C++ 4.0 bug.  FW_Minimum is a C++ template function
  42. //    and can't be used inside of SOMLINK (extern "C") functions.
  43.  
  44. inline long FW_Minimum(long a, long b)
  45.     { return a < b ? a : b; }
  46.  
  47. //========================================================================================
  48. //    class FW_CPrivSinkBuffer
  49. //
  50. //  This class implements a buffer for use with FW_OSinks, especially FW_CStorageUnitSinks.  
  51. //    Each call to FW_CStorageUnitSink::Read() results in the creation and destruction of an
  52. //    intermediate FW_CByteArray.  To eliminate some of the expense associated with that 
  53. //    operation, ReadPeek() and WritePeek() methods of FW_CStorageUnitSink use this class 
  54. //    to allow the buffering of data being read and/or written to/from a storage unit.
  55. //
  56. //    Note that none of the methods of this class actually do any reading or writing.
  57. //    The FW_OSink instance must obtain a pointer to the buffer in memory and fill it 
  58. //    with data.  This class is responsible only for maintaining the buffer and data 
  59. //    pertaining directly to it.
  60. //
  61. //    The "initialPosition" is the offset within the storage unit of the start of the
  62. //    buffer.  To write the bufffer, seek to GetInitialPosition() and write from GetAddress() 
  63. //    for GetBytesWritten() bytes.  To read, get the current position and pass it as the 
  64. //    'initialPosition' argument to Initialize().  When items are read using ReadPeek() 
  65. //    and ReadPeekAdvance(), do a su->GetPosition() and pass that as the first argument 
  66. //    to ReakPeek().  
  67. //
  68. //    Physically, the class *is* an FW_OBufferedSinkData.  Consequently, we can safely cast 
  69. //    from an FW_OBufferedSinkData* to an FW_CPrivSinkBuffer*.
  70. //
  71. //========================================================================================
  72.  
  73. class FW_CPrivSinkBuffer : public FW_OBufferedSinkData
  74. {
  75. public:
  76.     enum EBufferKind {
  77.         kInvalid,
  78.         kReadPeek,
  79.         kWritePeek
  80.     };
  81.  
  82.     enum {
  83.         kInvalidPosition = 0xDEADBABE
  84.     };
  85.  
  86.     // ----- Constructors, destructor, operators -----
  87.  
  88.     void Construct(FW_ORandomAccessSink* aSink, long fCapacity);
  89.     void Destruct();
  90.     
  91.     // ----- Getters & setters -----
  92.  
  93.     char*        GetAddress() const;
  94.     long        GetCapacity() const;
  95.     long        GetInitialPosition() const;
  96.     long        GetBytesWritten() const;
  97.     FW_Boolean     IsDirty() const;
  98.     FW_Boolean     IsValid() const;
  99.     
  100.     // ----- Buffer-management routines -----
  101.  
  102.     void         Initialize(EBufferKind kind, long initialPosition, long validBytes);
  103.         // Initializes the type and validity of the buffer.
  104.  
  105.     void        Invalidate();
  106.         // Marks the buffer as containing invalid data.  The buffer must
  107.         //   be re-initialized before the next ReadPeek or WritePeek.
  108.  
  109.     void*        ReadPeek(Environment* ev, long& availableReadBytes);
  110.         // Returns a pointer to the data in the buffer starting at currentPosition.
  111.         //   availableReadBytes returns the number of valid bytes in the buffer
  112.         //   returned.
  113.                    
  114.     void        ReadPeekAdvance(Environment* ev, long bytesRead);
  115.         // Advances the ReadPeek buffer to indicate that the user has read the
  116.         //   number of bytes specified by bytesRead.  
  117.         // This routine should be called after the user uses the data from the buffer.
  118.         //   Otherwise, the same bytes will be returned by the next ReadPeek.
  119.                          
  120.     void*        WritePeek(Environment* ev, long& availableWriteBytes);
  121.         // Returns a pointer to the buffer starting at currentPosition.  The
  122.         //   number of bytes available for writing is returned in availableWriteBytes.
  123.                     
  124.     void        WritePeekAdvance(Environment* ev, long bytesWritten);
  125.         // Advances the WritePeek buffer to indicate that the user has written the
  126.         //   number of bytes specified by bytesWritten starting at currentPosition.
  127.         // This routine should be alled after the user writes the data.  Otherwise,
  128.         //   the data could be overwritten by future writes.
  129.  
  130.     void        FlushAndInvalidate(Environment* ev);
  131.         // If the buffer is "dirty", it needs to be written to disk. 
  132.  
  133. private:
  134.  
  135.     FW_CPrivSinkBuffer(){}
  136.     ~FW_CPrivSinkBuffer(){}
  137.  
  138.     FW_CPrivSinkBuffer(const FW_CPrivSinkBuffer& otherBuffer);
  139.     FW_CPrivSinkBuffer& operator=(const FW_CPrivSinkBuffer&);
  140. };
  141.  
  142. //----------------------------------------------------------------------------------------
  143. //    FW_CPrivSinkBuffer::GetAddress
  144. //----------------------------------------------------------------------------------------
  145.  
  146. inline char* FW_CPrivSinkBuffer::GetAddress() const
  147. {
  148.     return fBuffer;
  149. }
  150.  
  151. //----------------------------------------------------------------------------------------
  152. //    FW_CPrivSinkBuffer::GetCapacity
  153. //----------------------------------------------------------------------------------------
  154.  
  155. inline long FW_CPrivSinkBuffer::GetCapacity() const
  156. {
  157.     return fCapacity;
  158. }
  159.  
  160. //----------------------------------------------------------------------------------------
  161. //    FW_CPrivSinkBuffer::GetBytesWritten
  162. //----------------------------------------------------------------------------------------
  163.  
  164. inline long FW_CPrivSinkBuffer::GetBytesWritten() const
  165. {
  166.     return fBytesWritten;
  167. }
  168.  
  169. //----------------------------------------------------------------------------------------
  170. //    FW_CPrivSinkBuffer::GetInitialPosition
  171. //----------------------------------------------------------------------------------------
  172.  
  173. inline long FW_CPrivSinkBuffer::GetInitialPosition() const
  174. {
  175.     return fInitialPosition;
  176. }
  177.  
  178. //----------------------------------------------------------------------------------------
  179. //    FW_CPrivSinkBuffer::IsDirty
  180. //----------------------------------------------------------------------------------------
  181.  
  182. inline FW_Boolean FW_CPrivSinkBuffer::IsDirty() const
  183. {
  184.     return fType == kWritePeek && GetBytesWritten() != 0;
  185. }
  186.  
  187. //----------------------------------------------------------------------------------------
  188. //    FW_CPrivSinkBuffer::IsValid
  189. //----------------------------------------------------------------------------------------
  190.  
  191. inline FW_Boolean FW_CPrivSinkBuffer::IsValid() const
  192. {
  193.     return fType != kInvalid && fInitialPosition != kInvalidPosition;
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. //    FW_CPrivSinkBuffer::Invalidate
  198. //----------------------------------------------------------------------------------------
  199.  
  200. inline void FW_CPrivSinkBuffer::Invalidate()
  201. {
  202.     Initialize(kInvalid, kInvalidPosition, 0);
  203. }
  204.  
  205. //----------------------------------------------------------------------------------------
  206. //    FW_CPrivSinkBuffer::Construct
  207. //
  208. //    This constructor just initializes some fields--no memory is actually allocated
  209. //    for the buffer until Initialize() is called.
  210. //----------------------------------------------------------------------------------------
  211.  
  212. void FW_CPrivSinkBuffer::Construct(FW_ORandomAccessSink* aSink, long capacity)
  213. {
  214.     fWrappedSink        = aSink;
  215.     fBuffer                = new char[capacity];
  216.     fCapacity            = capacity;
  217.     fValidBytes            = 0;
  218.     fInitialPosition    = kInvalidPosition;
  219.     fBytesWritten        = 0;
  220.     fType                = kInvalid;
  221. }
  222.  
  223. //----------------------------------------------------------------------------------------
  224. //    FW_CPrivSinkBuffer::Destruct
  225. //----------------------------------------------------------------------------------------
  226.  
  227. void FW_CPrivSinkBuffer::Destruct()
  228. {
  229.     delete [] fBuffer;
  230.     fBuffer = 0;
  231. }
  232.  
  233. //----------------------------------------------------------------------------------------
  234. //    FW_CPrivSinkBuffer::Initialize
  235. //----------------------------------------------------------------------------------------
  236.  
  237. void FW_CPrivSinkBuffer::Initialize(EBufferKind kind, long initialPosition, long validBytes)
  238. {
  239.     fValidBytes         = validBytes;
  240.     fInitialPosition = initialPosition;
  241.     fBytesWritten     = 0;
  242.     fType             = kind;
  243. }
  244.  
  245. //----------------------------------------------------------------------------------------
  246. //    FW_CPrivSinkBuffer::ReadPeek
  247. //----------------------------------------------------------------------------------------
  248.  
  249. void* FW_CPrivSinkBuffer::ReadPeek(Environment* ev, long& availableReadBytes)
  250. {
  251.     long currentPosition = fWrappedSink->GetPosition(ev);
  252.     void* source = 0;
  253.     availableReadBytes = 0;
  254.  
  255.     if (fType == kReadPeek && currentPosition >= fInitialPosition)
  256.     {
  257.         const long offsetInBuffer = currentPosition - fInitialPosition;
  258.  
  259.         if (offsetInBuffer < fValidBytes)
  260.         {
  261.             source = GetAddress() + offsetInBuffer;
  262.             availableReadBytes = fValidBytes - offsetInBuffer;
  263.         }
  264.     }
  265.  
  266.     // If there is no buffered data available, load the buffer.
  267.     if (availableReadBytes == 0)
  268.     {
  269.         // Write out any dirty data, mark the buffer invalid.  Stay at this seek position
  270.         if (IsDirty)
  271.         {
  272.             FlushAndInvalidate(ev);
  273.             fWrappedSink->SetPosition(ev, currentPosition);
  274.         }
  275.         else
  276.             Invalidate();
  277.  
  278.         // Determine the amount of data which will fit into the buffer and read it.  Seek
  279.         //    back to the point where the read began.  The buffer is still invalid: if an 
  280.         //    exception occurs, it remains invalid.  Only when the read&seek complete is the 
  281.         //    buffer marked as valid
  282.         availableReadBytes = FW_Minimum(fWrappedSink->GetReadableBytes(ev), GetCapacity());
  283.         fWrappedSink->Read(ev, GetAddress(), availableReadBytes);
  284.         fWrappedSink->SetPosition(ev, currentPosition);
  285.  
  286.         // Mark the buffer as containing valid data, peek into the buffer
  287.         Initialize(kReadPeek, currentPosition, availableReadBytes);
  288.         source = GetAddress();
  289.     }
  290.  
  291.     return source;
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. //    FW_CPrivSinkBuffer::ReadPeekAdvance
  296. //----------------------------------------------------------------------------------------
  297.  
  298. void FW_CPrivSinkBuffer::ReadPeekAdvance(Environment* ev, long bytesRead)
  299. {
  300.     long currentPosition = fWrappedSink->GetPosition(ev);
  301.  
  302.     fWrappedSink->SetPosition(ev, currentPosition + bytesRead);
  303.  
  304. #ifdef FW_DEBUG
  305.     FW_ASSERT(fType == kReadPeek);
  306.     FW_ASSERT(fInitialPosition <= currentPosition);
  307.     FW_ASSERT(bytesRead >= 0);
  308.     FW_ASSERT((currentPosition - fInitialPosition + bytesRead) <= fValidBytes);
  309. #endif
  310. }
  311.  
  312. //----------------------------------------------------------------------------------------
  313. //    FW_CPrivSinkBuffer::WritePeek
  314. //----------------------------------------------------------------------------------------
  315.  
  316. void* FW_CPrivSinkBuffer::WritePeek(Environment* ev, long& availableWriteBytes)
  317. {
  318.     long currentPosition = fWrappedSink->GetPosition(ev);
  319.     void* destination = 0;
  320.     availableWriteBytes = 0;
  321.  
  322.     // If no seeking has occurred, then the buffer is valid
  323.     if (fType == kWritePeek && currentPosition == fInitialPosition)
  324.     {
  325.         destination = GetAddress() + GetBytesWritten();
  326.         availableWriteBytes = fValidBytes - GetBytesWritten();
  327.     }
  328.  
  329.     // If buffer is invalid (for whatever reason), write the buffer and prepare for more.
  330.     if (availableWriteBytes == 0)
  331.     {
  332.         FW_Boolean repositionCursor = false;
  333.  
  334.         // Assure fWrappedSink->GetPosition(ev) == currentPosition after the
  335.         // call to FlushAndInvalidate()
  336.         if (IsDirty())
  337.         {
  338.             repositionCursor = (currentPosition != fInitialPosition);
  339.             if (!repositionCursor)
  340.                 currentPosition = GetInitialPosition() + GetBytesWritten();
  341.         }
  342.  
  343.         // Write out any dirty data, mark the buffer invalid.
  344.         FlushAndInvalidate(ev);
  345.  
  346.         // If the cursor is not where we want it, reposition it
  347.         if (repositionCursor)
  348.             fWrappedSink->SetPosition(ev, currentPosition);
  349.  
  350.         // The invariant.
  351.         FW_ASSERT(fWrappedSink->GetPosition(ev) == currentPosition);
  352.  
  353.         // Set the writable size for the buffer, peek into the buffer
  354.         availableWriteBytes = FW_Minimum(fWrappedSink->GetWritableBytes(ev), GetCapacity());
  355.         Initialize(kWritePeek, currentPosition, availableWriteBytes);
  356.         destination = GetAddress();
  357.     }
  358.  
  359.     return destination;
  360. }
  361.  
  362. //----------------------------------------------------------------------------------------
  363. //    FW_CPrivSinkBuffer::WritePeekAdvance
  364. //----------------------------------------------------------------------------------------
  365.  
  366. void FW_CPrivSinkBuffer::WritePeekAdvance(Environment* ev, long bytesWritten)
  367. {
  368. #ifdef FW_DEBUG
  369.     long currentPosition = fWrappedSink->GetPosition(ev);
  370.     FW_ASSERT(fType == kWritePeek);
  371. //    FW_ASSERT(GetBytesWritten() == (currentPosition - fInitialPosition));
  372.     FW_ASSERT(bytesWritten >= 0);
  373.     FW_ASSERT((GetBytesWritten() + bytesWritten) <= fValidBytes);
  374. #endif
  375.  
  376.     fBytesWritten += bytesWritten;
  377. }
  378.  
  379.  
  380. //----------------------------------------------------------------------------------------
  381. // FW_CPrivSinkBuffer::FlushAndInvalidate
  382. //----------------------------------------------------------------------------------------
  383. void FW_CPrivSinkBuffer::FlushAndInvalidate(Environment *ev)
  384. {
  385.     // If the buffer is dirty, write its contents
  386.     if (IsDirty())
  387.     {
  388.         fWrappedSink->SetPosition(ev, GetInitialPosition());
  389.         fWrappedSink->Write(ev, GetAddress(), GetBytesWritten());
  390.     }
  391.  
  392.     // Invalidate the buffer
  393.     Invalidate();
  394. }
  395.  
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // FW_OBufferedSink__InitFromSink
  399. //----------------------------------------------------------------------------------------
  400.  
  401. SOM_Scope void  SOMLINK FW_OBufferedSink__InitFromSink(FW_OBufferedSink *somSelf, Environment *ev,
  402.         FW_ORandomAccessSink* aSink,
  403.         long bufferCapacity)
  404. {
  405.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  406.  
  407.     FW_SOM_TRY
  408.     {
  409.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  410.         aSinkBuffer->Construct(aSink, bufferCapacity);
  411.     }
  412.     FW_SOM_CATCH
  413. }
  414.  
  415. //----------------------------------------------------------------------------------------
  416. // FW_OBufferedSink__GetORandomAccessSink
  417. //----------------------------------------------------------------------------------------
  418.  
  419. SOM_Scope FW_ORandomAccessSink*  SOMLINK FW_OBufferedSink__GetORandomAccessSink(FW_OBufferedSink *somSelf, Environment *ev)
  420. {
  421. FW_UNUSED(ev);
  422.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  423.     return _fWrappedSink;
  424. }
  425.  
  426. //----------------------------------------------------------------------------------------
  427. // FW_OBufferedSink__Flush
  428. //----------------------------------------------------------------------------------------
  429.  
  430. SOM_Scope void  SOMLINK FW_OBufferedSink__Flush(FW_OBufferedSink *somSelf, Environment *ev)
  431. {
  432.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  433.  
  434.     FW_SOM_TRY
  435.     {
  436.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  437.         aSinkBuffer->FlushAndInvalidate(ev);
  438.     }
  439.     FW_SOM_CATCH
  440. }
  441.  
  442. //----------------------------------------------------------------------------------------
  443. // FW_OBufferedSink__GetReadableBytes
  444. //----------------------------------------------------------------------------------------
  445.  
  446. SOM_Scope long  SOMLINK FW_OBufferedSink__GetReadableBytes(FW_OBufferedSink *somSelf, Environment *ev)
  447. {
  448.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  449.  
  450.     FW_SOM_TRY
  451.     {
  452.         return _fWrappedSink->GetReadableBytes(ev);
  453.     }
  454.     FW_SOM_CATCH
  455.     return 0;
  456. }
  457.  
  458. //----------------------------------------------------------------------------------------
  459. // FW_OBufferedSink__Read
  460. //----------------------------------------------------------------------------------------
  461.  
  462. SOM_Scope void  SOMLINK FW_OBufferedSink__Read(FW_OBufferedSink *somSelf, Environment *ev,
  463.         void* destination,
  464.         long count)
  465. {
  466.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  467.  
  468.     FW_SOM_TRY
  469.     {
  470.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  471.         long availableReadBytes;
  472.         const char* currentSource = (char*)aSinkBuffer->ReadPeek(ev, availableReadBytes);
  473.         long bytesToReadThisTime = FW_Minimum(count, availableReadBytes);
  474.  
  475.         // [jkp] 960215 Optimizing large data transfers
  476.         //    Possible future optimization is to check if "availableReadBytes" is 
  477.         //    greater than "bytesToReadThisTime + _fCapacity".  In that case, we 
  478.         //    can read what's in the buffer, invalidate the buffer, read the remainder 
  479.         //    directly from the sink.  This avoids double-copying of the data: once 
  480.         //    from the sink to the buffer, then from the buffer to the destination.
  481.         //
  482.         //    This hasn't been done because streams are used for many transfers of small 
  483.         //    data: buffering wins.  Also, the developer can grab the underlying sink and 
  484.         //    transfer directly.  The buffered sink "catches up" when the seek pointer has 
  485.         //    moved.
  486.         while (bytesToReadThisTime != 0)
  487.         {
  488.             FW_PrimitiveCopyMemory(currentSource, destination, bytesToReadThisTime);
  489.             aSinkBuffer->ReadPeekAdvance(ev, bytesToReadThisTime);
  490.             destination = (char*)destination + bytesToReadThisTime;
  491.             count -= bytesToReadThisTime;
  492.             if (count == 0)
  493.                 break;
  494.             currentSource = (const char*)aSinkBuffer->ReadPeek(ev, availableReadBytes);
  495.             bytesToReadThisTime = FW_Minimum(count, availableReadBytes);
  496.         }
  497.  
  498.         if (count != 0)
  499.             FW_Failure(FW_xReadableStream);
  500.     }
  501.     FW_SOM_CATCH
  502. }
  503.  
  504. //----------------------------------------------------------------------------------------
  505. // FW_OBufferedSink__GetWritableBytes
  506. //----------------------------------------------------------------------------------------
  507.  
  508. SOM_Scope long  SOMLINK FW_OBufferedSink__GetWritableBytes(FW_OBufferedSink *somSelf, Environment *ev)
  509. {
  510.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  511.  
  512.     FW_SOM_TRY
  513.     {
  514.         return _fWrappedSink->GetWritableBytes(ev);
  515.     }
  516.     FW_SOM_CATCH
  517.     return 0;
  518. }
  519.  
  520. //----------------------------------------------------------------------------------------
  521. // FW_OBufferedSink__Write
  522. //----------------------------------------------------------------------------------------
  523.  
  524. SOM_Scope void  SOMLINK FW_OBufferedSink__Write(FW_OBufferedSink *somSelf, Environment *ev,
  525.         void* source,
  526.         long count)
  527. {
  528.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  529.  
  530.     FW_SOM_TRY
  531.     {
  532.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  533.         long availableWriteBytes;
  534.         char* currentDestination = (char*)aSinkBuffer->WritePeek(ev, availableWriteBytes);
  535.         long bytesToWriteThisTime = FW_Minimum(count, availableWriteBytes);
  536.  
  537.         while (bytesToWriteThisTime != 0)
  538.         {
  539.             FW_PrimitiveCopyMemory(source, currentDestination, bytesToWriteThisTime);
  540.             aSinkBuffer->WritePeekAdvance(ev, bytesToWriteThisTime);
  541.             source = (char*)source + bytesToWriteThisTime;
  542.             count -= bytesToWriteThisTime;
  543.             if (count == 0)
  544.                 break;
  545.             currentDestination = (char*)aSinkBuffer->WritePeek(ev, availableWriteBytes);
  546.             bytesToWriteThisTime = FW_Minimum(count, availableWriteBytes);
  547.         }
  548.  
  549.         if (count != 0)
  550.             FW_Failure(FW_xWritableStream);
  551.     }
  552.     FW_SOM_CATCH
  553. }
  554.  
  555. //----------------------------------------------------------------------------------------
  556. // FW_OBufferedSink__GetLength
  557. //----------------------------------------------------------------------------------------
  558.  
  559. SOM_Scope long  SOMLINK FW_OBufferedSink__GetLength(FW_OBufferedSink *somSelf, Environment *ev)
  560. {
  561.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  562.  
  563.     FW_SOM_TRY
  564.     {
  565.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  566.  
  567.         if (aSinkBuffer->IsDirty())
  568.             aSinkBuffer->FlushAndInvalidate(ev);
  569.         return _fWrappedSink->GetLength(ev);
  570.     }
  571.     FW_SOM_CATCH
  572.     return 0;
  573. }
  574.  
  575. //----------------------------------------------------------------------------------------
  576. // FW_OBufferedSink__SetLength
  577. //----------------------------------------------------------------------------------------
  578.  
  579. SOM_Scope void  SOMLINK FW_OBufferedSink__SetLength(FW_OBufferedSink *somSelf, Environment *ev,
  580.         long length)
  581. {
  582.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  583.  
  584.     FW_SOM_TRY
  585.     {
  586.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  587.  
  588.         aSinkBuffer->FlushAndInvalidate(ev);
  589.         _fWrappedSink->SetLength(ev, length);
  590.     }
  591.     FW_SOM_CATCH
  592. }
  593.  
  594. //----------------------------------------------------------------------------------------
  595. // FW_OBufferedSink__GetPosition
  596. //----------------------------------------------------------------------------------------
  597.  
  598. SOM_Scope long  SOMLINK FW_OBufferedSink__GetPosition(FW_OBufferedSink *somSelf, Environment *ev)
  599. {
  600.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  601.  
  602.     FW_SOM_TRY
  603.     {
  604.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  605.  
  606.         if (aSinkBuffer->IsDirty())
  607.             aSinkBuffer->FlushAndInvalidate(ev);
  608.         return _fWrappedSink->GetPosition(ev);
  609.     }
  610.     FW_SOM_CATCH
  611.     return 0;
  612. }
  613.  
  614. //----------------------------------------------------------------------------------------
  615. // FW_OBufferedSink__SetPosition
  616. //----------------------------------------------------------------------------------------
  617.  
  618. SOM_Scope void  SOMLINK FW_OBufferedSink__SetPosition(FW_OBufferedSink *somSelf, Environment *ev,
  619.         long position)
  620. {
  621.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  622.  
  623.     FW_SOM_TRY
  624.     {
  625.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  626.  
  627.         if (aSinkBuffer->IsDirty())
  628.             aSinkBuffer->FlushAndInvalidate(ev);
  629.         _fWrappedSink->SetPosition(ev, position);
  630.     }
  631.     FW_SOM_CATCH
  632. }
  633.  
  634. //----------------------------------------------------------------------------------------
  635. // FW_OBufferedSink__somInit
  636. //----------------------------------------------------------------------------------------
  637.  
  638. SOM_Scope void  SOMLINK FW_OBufferedSink__somInit(FW_OBufferedSink *somSelf)
  639. {
  640.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  641.  
  642.     FW_OBufferedSink_parent_FW_ORandomAccessSink_somInit(somSelf);
  643. }
  644.  
  645. //----------------------------------------------------------------------------------------
  646. // FW_OBufferedSink__somUninit
  647. //----------------------------------------------------------------------------------------
  648.  
  649. SOM_Scope void  SOMLINK FW_OBufferedSink__somUninit(FW_OBufferedSink *somSelf)
  650. {
  651.     FW_OBufferedSinkData *somThis = FW_OBufferedSinkGetData(somSelf);
  652.  
  653.     FW_SOM_UNINIT_TRY
  654.     {
  655.         FW_CPrivSinkBuffer* aSinkBuffer = (FW_CPrivSinkBuffer*)somThis;
  656.         FW_SOMEnvironment ev;
  657.  
  658.         // Flush out any data which hasn't been written, then reclaim memory.
  659.         aSinkBuffer->FlushAndInvalidate(ev);
  660.         aSinkBuffer->Destruct();
  661.  
  662.         FW_OBufferedSink_parent_FW_ORandomAccessSink_somInit(somSelf);
  663.     }
  664.     FW_SOM_UNINIT_CATCH
  665. }
  666.